#!/usr/bin/env python3

import os
import json
import shutil
import tempfile
import gitee_api
import urllib.request
from collections import defaultdict

distribution = 'ukylin'


def parse_sig_yaml(repo_path):
    repositories = defaultdict(lambda: defaultdict(set))
    sig_yaml_path = os.path.join(repo_path, 'sig/sig.yaml')
    if not os.path.exists(sig_yaml_path):
        return repositories
    import yaml
    data = yaml.load(open(sig_yaml_path))

    global distribution
    distribution = data['distribution']

    for sig in data['sig']:
        # sig maintainers
        maintainers = [user['name'] for user in sig['maintainers']]
        owner = sig['owner']
        for package in sig['packages']:
            repositories[package]['owner'] = owner
            repositories[package]['maintainers'].union(maintainers)
            repositories[package]['maintainers'].add(owner)

    # all package
    all = repositories.pop('all')
    for package in repositories:
        repositories[package]['maintainers'].union(all['maintainers'])

    return repositories


def clone_repo(repo_url):
    repo_path = tempfile.mkdtemp()
    ret = os.system(f"git clone '{repo_url}' {repo_path}")
    if ret != 0:
        raise Exception('clone repository failed')
    return repo_path


def patch_repo(repo_path, diff_url):
    patch_data = urllib.request.urlopen(diff_url).read()
    patch_path = tempfile.mktemp()
    with open(patch_path, 'wb') as f:
        f.write(patch_data)
    os.chdir(repo_path)
    ret = os.system(f'git apply {patch_path}')
    os.remove(patch_path)
    if ret != 0:
        raise Exception('patch failed')
    return


def do_sig_operation(old, new):
    gitee_token = os.environ['GiteeToken']
    gitee_client = gitee_api.GiteeAPIClient(distribution, token=gitee_token)
    me = gitee_client.current_user()
    # sig中去掉的项目，删除所有maintainer，owner改成sig-bot自己
    for package in set(old.keys()) - set(new.keys()):
        # 获取用户名列表
        users = gitee_client.get_repo_collaborator()
        # sig-bot用户添加到admin
        if me not in [user['login'] for user in users]:
            gitee_client.add_repo_collaborator(package, me, 'admin')
        for user in users:
            if user['login'] != me:
                # 删除其余用户
                gitee_client.del_repo_collaborator(package, user['login'])

    # sig新增项目
    for package in set(new.keys()) - set(old.keys()):
        gitee_client.create_e_repo(
            package, private=1, members=new[package]['maintainers'])
        # 检查用户是否都在里面了
        current_members = gitee_client.get_repo_collaborator(package)
        for newuser in set(new[package]['maintainers']) - set([user['login'] for user in current_members]):
            gitee_client.add_repo_collaborator(
                package, newuser, permission='push')

    # 改变maintainer的项目
    for package in set(old.keys()) & set(new.keys()):
        old_users = old[package]['maintainers']
        new_users = new[package]['maintainers']
        # 添加新用户，删除旧用户
        for username in old_users - new_users:
            gitee_client.del_repo_collaborator(package, username)
        for username in new_users - old_users:
            gitee_client.add_repo_collaborator(
                package, username, permission='push')


def main():
    hook_data = json.loads(os.environ['jsonBody'])
    # get current sig
    repo_path = clone_repo(
        repo_url=hook_data['target_repo']['repository']['clone_url'])
    old = parse_sig_yaml(repo_path)

    # patch
    patch_repo(repo_path, diff_url=hook_data['pull_request']['diff_url'])
    new = parse_sig_yaml(repo_path)

    # do sig
    do_sig_operation(old, new)

    # clean
    shutil.rmtree(repo_path)


if __name__ == '__main__':
    main()
